package tau.dimes.util;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

public class ReflectionHelper
{
	public static Map<Class<?>, Map<String, PropertyDescriptor>> cache = new HashMap<Class<?>, Map<String, PropertyDescriptor>>();

	public static void SetProperties(Object obj, Map<String, String> properties)
		throws IntrospectionException, IllegalArgumentException, IllegalAccessException,
		InvocationTargetException, NoSuchMethodException
	{
		Class<?> c = obj.getClass();
		if (!isInCache(c))
			storeInCache(c);
		
		Map<String, PropertyDescriptor> pdMap = getFromCache(c);

		for (String propertyName : properties.keySet())
		{
			PropertyDescriptor pd = pdMap.get(propertyName);
			if (pd == null)
				throw new NoSuchMethodException("No such property: " + propertyName);
			Method writeMethod = pd.getWriteMethod();
			writeMethod.invoke(obj, properties.get(propertyName));
		}
	}
	
	private static boolean isInCache(Class<?> c)
	{
		return cache.containsKey(c);
	}
	
	private static Map<String, PropertyDescriptor> getFromCache(Class<?> c)
	{
		return cache.get(c);
	}
	
	private static void storeInCache(Class<?> c) throws IntrospectionException
	{
		Map<String, PropertyDescriptor> pdMap = new TreeMap<String, PropertyDescriptor>();
		BeanInfo beanInfo = Introspector.getBeanInfo(c);
		PropertyDescriptor[] pdArray = beanInfo.getPropertyDescriptors();
		
		for (PropertyDescriptor pd : pdArray)
			pdMap.put(pd.getName(), pd);
		
		cache.put(c, pdMap);
	}
}
